package com.internetCafes.spms.web.job.task.sys;

import cn.hutool.core.collection.CollectionUtil;
import com.internetCafes.spms.common.CommonConstants;
import com.internetCafes.spms.common.module.sms.SmsAlidayu;
import com.internetCafes.spms.core.utils.DateUtils;
import com.internetCafes.spms.web.certificate.service.CertificateInfoService;
import com.internetCafes.spms.web.certificate.vo.CertificateInfoVo;
import com.internetCafes.spms.web.sys.bizservice.sms.SysSmsUserSendConfBizService;
import com.internetCafes.spms.web.sys.common.cont.SmsSendConfConst;
import com.internetCafes.spms.web.sys.model.SmsLog;
import com.internetCafes.spms.web.sys.model.UserInfo;
import com.internetCafes.spms.web.sys.service.SmsLogService;
import com.internetCafes.spms.web.sys.service.UserInfoService;
import com.internetCafes.spms.web.tenant.model.TenantInfo;
import com.internetCafes.spms.web.tenant.service.TenantInfoService;
import lombok.extern.log4j.Log4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Log4j
@Component("certificateComponentTask")
public class CertificateComponentTask {

    @Autowired
    private CertificateInfoService certificateInfoService;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private TenantInfoService tenantInfoService;

    @Autowired
    private SmsLogService smsLogService;

    @Autowired
    private SysSmsUserSendConfBizService smsUserSendConfBizService;

    /**
     * 短信开头称呼
     */
    private final String MSG_START_CALL_PREFIX = "尊敬的";
    private final String MSG_START_CALL_SUFFIX = "用户,贵公司有";
    private final String MSG_FIRST_SUFFIX = ",注意及时处理。";
    private final String MSG_MORE = "还有";
    private final String MSG_PERIOD = "。";
    private final String MSG_COMMA = ",";
    private final String MSG_EXPIRE_SEVEN_DATE = "本证书将在7天内到期";
    private final String MSG_EXPIRE_FIFTEEN_DATE = "本证书将在15天内到期";
    private final String MSG_EXPIRE_NINETY_DATE = "本证书将在90天内到期";

    /**
     * 短信发送标识 1-成功 0-失败
     */
    private final Integer MSG_SEND_STATUS_SUCCESS = 1;
    private final Integer MSG_SEND_STATUS_ERROR = 0;

    /**
     * 过期模板
     */
    /*private final String MSG_EXPIRE_TEMPLATE = "{AMOUNT}本证书将在{DATA}天后到期";

    private final String MSG_TENANT_CALL_PREFIX = "尊敬的{DEPT_NAME}用户,贵单位有{MSG_EXPIRE_TEMPLATE},注意及时处理。";

    private final String MSG_TENANT_CALL = "还有{MSG_EXPIRE_TEMPLATE}";*/

    /**
     * 三个月内到期，一个星期发一次短信
     * 定时任务执行间隔:每天早上九点
     * <p>
     * 情况1，三种到期期限证书都有:【虹合科技】尊敬的*用户,贵单位有*本证书将在7天后到期,注意及时处理。还有*本证书将在15天后到期,*本证书将在90天后到期。
     * <p>
     * 情况2，有两种到期期限证书【虹合科技】尊敬的*用户,贵单位有*本证书将在*天后到期,注意及时处理。还有*本证书将在*天后到期。
     * <p>
     * 情况3，有一种到期期限证书【虹合科技】尊敬的*用户,贵单位有*本证书将在*天后到期,注意及时处理。
     * <p>
     * 如没有需要预警证书，则不发送短信。发送短信时到期时间近的放在前面。
     * <p>
     * 早上10点，
     * 文案【银田网络】尊敬的*用户,贵公司有*本证书将在7天内到期,*本15天内到期,*本在90天内到期。
     * 注意：15内包括7天内的数量
     * 发送规则：当天有7天、15、90到期的证书发送通知，其他情况不发送。
     */
    /*@Scheduled(cron = "0 40 15 * * ?")*/

    /**
     * 发送标签 发送
     */
    private final static String SEND_FLAG = "true";

    /**
     * 证书过期短信发送
     * <p>
     * 证书过期发送定时器测试
     * </p>
     *
     * @param sendFlag 线上测试，入参 有且环境为pro sendFlag为"true"的时候短信进行发送，其余仅仅保存到数据库
     * @author Zj
     */
    public void sendCertificateExpireMessage(String sendFlag) {

        // 获取环境判断短信是否真的发送
        Integer smsStatus = SEND_FLAG.equals(sendFlag) ? MSG_SEND_STATUS_SUCCESS : MSG_SEND_STATUS_ERROR;
        log.info("smsStatus is:" + smsStatus);

        /* 2021/4/7
         * 		1-获取将90天过期的证书信息 7 - 0 15 - 7 90 - 15 三级 已过期不提示
         * 		2-短信内容封装
         */
        // 1-获取需要通知的企业id列表
        List<Long> deptIds = tenantInfoService.getTenantsOfExpireNotice();
        if (CollectionUtils.isEmpty(deptIds)) {
            log.info("无需要预警证书过期部门");
            return;
        }
        log.info("开始获取预警证书数据");
        // 2-获取对应证书信息后根据企业ID进行分组
        List<CertificateInfoVo> certificateInfoVos = certificateInfoService.selectExpireInfo(deptIds);
        Map<Long, List<CertificateInfoVo>> groupByTenantId = certificateInfoVos.stream()
                .collect(Collectors.groupingBy(CertificateInfoVo::getTenantId));

        // 3-获取对应租户的用户信息
        // 修改 2022-05-30 添加短信发送配置，对账号开通短信功能进行控制,需要过滤掉没有配置该功能的用户
        List<String> filterMobileList = smsUserSendConfBizService.listMobileByFunctionCode(SmsSendConfConst.FunctionCode.CERTIFICATE_EXPIRE_WARNING.getCode());
        if (CollectionUtil.isEmpty(filterMobileList)) {
            return;
        }
        filterMobileList = CollectionUtil.distinct(filterMobileList);
        Map<String, Object> params = new HashMap<>();
        params.put("deptIds", deptIds);
        params.put("status", CommonConstants.CommonStatus.ENABLE);
        List<UserInfo> userInfos = userInfoService.queryList(params);

        List<String> finalFilterMobileList = filterMobileList;
        Map<Long, List<UserInfo>> tenantUsers = userInfos.stream()
                .filter(po -> finalFilterMobileList.contains(po.getMobile()))
                .collect(Collectors.groupingBy(UserInfo::getDeptId));

        // 4-获取对应租户的信息数据
        Map<String, Object> params2 = new HashMap<>();
        params2.put("ids", deptIds);
        List<TenantInfo> tenants = tenantInfoService.query(params2);
        Map<Long, List<TenantInfo>> tenantsByTenantId = tenants.stream()
                .collect(Collectors.groupingBy(TenantInfo::getTenantId));


        // 5-解析分组之后的数据,获取各个阶段各数据
        long countTotal, tenantId;
        List<Long> counts;
        List<SmsLog> smss = new ArrayList<>();
        for (Map.Entry<Long, List<CertificateInfoVo>> tenantCertificateInfoVos : groupByTenantId.entrySet()) {
            // 租户id
            tenantId = tenantCertificateInfoVos.getKey();
            // 短信数量计算统计
            counts = new ArrayList<>();
            countTotal = tenantCertificateInfoVos.getValue().size();
            long innerSevenTotal = tenantCertificateInfoVos.getValue().stream()
                    .filter(infoTemp -> (infoTemp.getValidityEndTime().before(DateUtils.getBeAfDay(7))))
                    .count();
            long innerFifteenTotal = tenantCertificateInfoVos.getValue().stream()
                    .filter(infoTemp -> (infoTemp.getValidityEndTime().before(DateUtils.getBeAfDay(15))
                            && infoTemp.getValidityEndTime().after(DateUtils.getBeAfDay(7))))
                    .count();
            long innerNinetyTotal = countTotal - innerSevenTotal - innerFifteenTotal;
            counts.add(innerSevenTotal);
            counts.add(innerFifteenTotal);
            counts.add(innerNinetyTotal);

            String tenantName = tenantsByTenantId.get(tenantId).get(0).getTenantName();
            // 短信内容封装
            String finalContent = assembleMessage(tenantName, counts);
            if (!"".equals(finalContent)) {
                List<UserInfo> users = tenantUsers.get(tenantId);
                if (users != null) {
                    // 排除掉手机号为空的情况
                    users.stream().filter(user -> user.getMobile() != null).forEach(tenantUser -> {
                        // 发送短信
                        if (SEND_FLAG.equals(sendFlag)) {
                            SmsAlidayu.sendExpireNotice(tenantUser.getMobile(), tenantName, innerSevenTotal, innerFifteenTotal, innerNinetyTotal);
                        }
                        smss.add(new SmsLog(2, tenantUser.getDeptId(), tenantUser.getUserId(),
                                tenantUser.getNickName(), tenantUser.getMobile(), finalContent, smsStatus));
                    });
                }
            }
        }
        // 短信保存
        if (CollectionUtil.isNotEmpty(smss)) {
            smsLogService.saveBatch(smss);
        }
    }

    /**
     * 手机号码过滤
     */
    private static List<String> mobileFilter = new ArrayList<>();

    static {
        mobileFilter.add("15067757774");
        mobileFilter.add("15158527369");
        mobileFilter.add("15988112540");
        mobileFilter.add("15068972290");
        mobileFilter.add("15905772957");
        mobileFilter.add("15205871315");
        mobileFilter.add("13587854882");
        mobileFilter.add("13566255268");
        mobileFilter.add("15267769682");
        mobileFilter.add("13675892929");
        mobileFilter.add("13063085065");
        mobileFilter.add("13037617240");
        mobileFilter.add("13063085065");
        mobileFilter.add("18621742606");
        mobileFilter.add("18736943520");
    }

    /**
     * 组装短信信息
     *
     * @return 结果
     * By Zheng
     */
    private String assembleMessage(String deptName, List<Long> counts) {
        /*尊敬的*用户,贵单位有*本证书将在7天后到期,注意及时处理。还有*本证书将在15天后到期,*本证书将在90天后到期。*/
        long amount = counts.stream()
                .filter(s -> !s.equals(0L))
                .count();
        if (amount == 0L) {
            return "";
        }
        return "【虹合科技】尊敬的" + deptName + "用户，贵单位有" + counts.get(0) + "本证书将在7天内到期," + counts.get(1) + "本证书将在15天内到期," + counts.get(2) + "本证书将在90天内到期";
        /*long amount = counts.stream()
                .filter(s -> !s.equals(0L))
                .count();
        if (amount == 0l) {
            return "";
        }
        StringBuilder stringBuilder = new StringBuilder("【虹合科技】");
        stringBuilder.append(MSG_START_CALL_PREFIX).append(deptName).append(MSG_START_CALL_SUFFIX);
        splicingExpireAmountAndDate(counts, stringBuilder);
        stringBuilder.append(MSG_FIRST_SUFFIX);
        if (amount == 1l) {
            return stringBuilder.toString();
        }
        stringBuilder.append(MSG_MORE);
        splicingExpireAmountAndDate(counts, stringBuilder);
        if (amount == 2l) {
            return stringBuilder.append(MSG_PERIOD).toString();
        }
        stringBuilder.append(MSG_COMMA);
        splicingExpireAmountAndDate(counts, stringBuilder);
        if (amount == 3l) {
            return stringBuilder.append(MSG_PERIOD).toString();
        }
        return "";*/
    }

    /**
     * *本证书将在*天内到期 语段拼接
     *
     * @param counts        数量
     * @param stringBuilder 拼接字符串
     * @author Zj
     */
    private void splicingExpireAmountAndDate(List<Long> counts, StringBuilder stringBuilder) {
        for (int i = 0; i < counts.size(); i++) {
            if (i == 0 && !counts.get(0).equals(0L)) {
                stringBuilder.append(counts.get(0)).append(MSG_EXPIRE_SEVEN_DATE);
                counts.set(0, 0L);
                break;
            }
            if (i == 1 && !counts.get(1).equals(0L)) {
                stringBuilder.append(counts.get(1)).append(MSG_EXPIRE_FIFTEEN_DATE);
                counts.set(1, 0L);
                break;
            }
            if (i == 2 && !counts.get(2).equals(0L)) {
                stringBuilder.append(counts.get(2)).append(MSG_EXPIRE_NINETY_DATE);
                counts.set(2, 0L);
                break;
            }
        }
    }
}
